package com.originit.order.server.service.impl;

import com.originit.order.server.dao.OrderDetailRepository;
import com.originit.order.server.dao.OrderMasterRepository;
import com.originit.order.server.dto.OrderDTO;
import com.originit.order.server.entity.OrderMaster;
import com.originit.order.server.enums.OrderStatus;
import com.originit.order.server.enums.PayStatus;
import com.originit.order.server.enums.ResultEnum;
import com.originit.order.server.exception.OrderException;
import com.originit.order.server.service.OrderService;
import com.originit.order.server.util.KeyUtil;
import com.originit.product.client.ProductClient;
import com.originit.product.common.input.CartInput;
import com.originit.product.common.output.ProductOutput;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

@Service
@Slf4j
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderMasterRepository orderMasterRepository;

    @Autowired
    private OrderDetailRepository orderDetailRepository;

    @Autowired
    private ProductClient productClient;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public OrderDTO create(OrderDTO orderDTO) {
        /**
         * 1. 获取产品信息
         * 2.
         */
        OrderMaster orderMaster = new OrderMaster();
        // 生成唯一的主键
        orderDTO.setOrderId(KeyUtil.generateUniqueKey());
        BeanUtils.copyProperties(orderDTO,orderMaster);
        orderMaster.setOrderStatus(OrderStatus.NEW.getCode());
        orderMaster.setPayStatus(PayStatus.WAIT.getCode());
        orderMaster.setCreateTime(LocalDateTime.now());
        orderMaster.setUpdateTime(LocalDateTime.now());
        // 从商品服务获取商品信息并转化为map
        Map<String, ProductOutput> productMap = productClient.listById(orderDTO.getDetailList()
                .stream()
                .map(orderDetail -> orderDetail.getProductId())
                .collect(Collectors.toList())
        ).stream().collect(Collectors.toMap(productInfo -> {
            return productInfo.getProductId();
        }, productInfo -> {
            return productInfo;
        }));
        // 用于记录当前库存的map
        List<CartInput> carts = new ArrayList<>();
        AtomicReference<BigDecimal> priceAmount = new AtomicReference<>(new BigDecimal(0));
        // 根据商品信息对订单详情补全，并检查库存
        orderDTO.getDetailList().forEach(orderDetail -> {
            ProductOutput productInfo = productMap.get(orderDetail.getProductId());
            if (productInfo == null) {
                log.error("【创建商品详情】商品详情找不到，id={}",orderDetail.getProductId());
                throw new OrderException("商品信息无效");
            }
            if (productInfo.getProductStock() < orderDetail.getProductQuantity()) {
                log.error("【创建商品详情】库存不够,id={},库存={},需求={}",orderDetail.getProductId(),
                        productInfo.getProductStock(),orderDetail.getProductQuantity());
                throw new OrderException(String.format("%s 库存不足",productInfo.getProductName(),
                        ResultEnum.GOOD_STOCK_NOT_ENOUGH));
            }
            BeanUtils.copyProperties(productInfo, orderDetail);
            orderDetail.setCreateTime(LocalDateTime.now());
            orderDetail.setUpdateTime(LocalDateTime.now());
            orderDetail.setOrderId(orderMaster.getOrderId());
            orderDetail.setDetailId(KeyUtil.generateUniqueKey());
            priceAmount.set(priceAmount.get().add(orderDetail.getProductPrice().multiply(new BigDecimal(orderDetail.getProductQuantity()))));
            // 记录当前库存
            carts.add(new CartInput(productInfo.getProductId(), orderDetail.getProductQuantity()));
        });
        // 减库存
        productClient.minusStockByIds(carts);
        // 设置订单总价
        orderMaster.setOrderAmount(priceAmount.get());
        // 保存订单详情
        orderDetailRepository.saveAll(orderDTO.getDetailList());
        // 保存订单
        orderMasterRepository.save(orderMaster);
        return orderDTO;
    }
}
